package com.qs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qs.constant.CacheConstant;
import com.qs.exception.ServiceException;
import com.qs.mapper.*;
import com.qs.model.entity.*;
import com.qs.model.enums.PayInfoEnum;
import com.qs.model.vo.OrderInfoVo;
import com.qs.response.ResponseEnum;
import com.qs.service.IAsyncService;
import com.qs.service.IPayInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 订单支付记录表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-03-30
 */
@Service
@RequiredArgsConstructor
public class PayInfoServiceImpl extends ServiceImpl<PayInfoMapper, PayInfo> implements IPayInfoService {

    private final StoreMapper storeMapper;
    private final GoodsMapper goodsMapper;
    private final OrderItemMapper orderItemMapper;
    private final RedisTemplate redisTemplate;
    private final IAsyncService asyncService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handlePay(String orderId) {
        QueryWrapper<PayInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id", orderId);
        PayInfo payInfo = baseMapper.selectOne(wrapper);
        if (payInfo == null) {
            throw new ServiceException(ResponseEnum.PAY_FOR_FAIL);
        }
        payInfo.setStatus(PayInfoEnum.HAVE_PAY);
        baseMapper.updateById(payInfo);

        //异步保存一条支付记录：qs_user_goods_log
        OrderItem orderItem = orderItemMapper.selectOne(new QueryWrapper<OrderItem>()
                .eq("order_id", orderId));
        Goods goods = goodsMapper.selectById(orderItem.getGoodsId());
        Store store = storeMapper.selectById(goods.getStoreId());
        UserGoodsLog userGoodsLog = new UserGoodsLog();
        userGoodsLog.setOrderId(orderId);
        userGoodsLog.setUserId(payInfo.getUserId());
        userGoodsLog.setGoodsId(orderItem.getGoodsId());
        userGoodsLog.setStoreId(store.getId());
        asyncService.saveUserGoodsLog(userGoodsLog);

    }

    @Override
    public List<OrderInfoVo> queryWaitPayOrder(Integer userId) {
        //待付款订单的定义为订单时间还在15分钟内的订单
        return this.getWaitPayOrder(userId);
    }

    @Override
    public List<OrderInfoVo> queryHistoryOrder(Integer userId) {
        //历史订单的定义为已付款的所有订单
        return this.getHistoryOrder(userId);
    }

    @Override
    public int queryWaitPayOrderCount(Integer userId) {
        //待付款的订单首先状态肯定是未支付，也就是状态为0
        QueryWrapper<PayInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.eq("status",PayInfoEnum.WAIT_PAY.getCode());
        wrapper.orderByDesc("create_time");
        List<PayInfo> payInfos = baseMapper.selectList(wrapper);
        //状态为未支付的订单包括待付款订单和超时订单，将待付款订单过滤出来
        if(!CollectionUtils.isEmpty(payInfos)){
            List<String> orderIds = new ArrayList<>();
            payInfos.stream().forEach(payInfo ->{
                String orderId = (String) redisTemplate.opsForValue().get(CacheConstant.ORDER_ID_CODE + payInfo.getOrderId());
                if(null != orderId){
                    //未超时订单
                    orderIds.add(orderId);
                }
            });
            return orderIds.size();
        }
        return 0;
    }

    /**
     * 待付款订单的定义为订单时间还在15分钟内的订单
     * @param userId
     * @return
     */
    private List<OrderInfoVo> getWaitPayOrder(Integer userId) {
        //待付款的订单首先状态肯定是未支付，也就是状态为0
        QueryWrapper<PayInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.eq("status",PayInfoEnum.WAIT_PAY.getCode());
        wrapper.orderByDesc("create_time");
        List<PayInfo> payInfos = baseMapper.selectList(wrapper);
        //状态为未支付的订单包括待付款订单和超时订单，将待付款订单过滤出来
        if(!CollectionUtils.isEmpty(payInfos)) {
            List<String> orderIds = new ArrayList<>();
            payInfos.stream().forEach(payInfo ->{
                String orderId = (String) redisTemplate.opsForValue().get(CacheConstant.ORDER_ID_CODE + payInfo.getOrderId());
                if(null != orderId){
                    //未超时订单
                    orderIds.add(orderId);
                }
            });
            if(!CollectionUtils.isEmpty(orderIds)){
                List<PayInfo> waitPayOrder = new ArrayList<>();
                orderIds.stream().forEach(orderId -> {
                    PayInfo payInfo = baseMapper.selectOne(new QueryWrapper<PayInfo>().eq("order_id", orderId));
                    waitPayOrder.add(payInfo);
                });
                //封装最后数据
                return this.packageData(waitPayOrder);
            }
        }
        return null;
    }

    /**
     * 历史订单的定义为已付款的所有订单
     * @param userId
     * @return
     */
    private List<OrderInfoVo> getHistoryOrder(Integer userId) {
        QueryWrapper<PayInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.eq("status",PayInfoEnum.HAVE_PAY.getCode());
        wrapper.orderByDesc("create_time");
        List<PayInfo> payInfos = baseMapper.selectList(wrapper);
        if(!CollectionUtils.isEmpty(payInfos)){
            return this.packageData(payInfos);
        }
        return null;
    }

    /**
     * 封装数据
     * @param payInfos
     * @return
     */
    private List<OrderInfoVo> packageData(List<PayInfo> payInfos) {
        List<OrderInfoVo> list = new ArrayList<>();
        payInfos.stream().forEach(payInfo -> {
            //封装订单详细数据
            OrderItem orderItem = orderItemMapper
                    .selectOne(new QueryWrapper<OrderItem>()
                    .eq("order_id", payInfo.getOrderId()));
            Goods goods = goodsMapper.selectById(orderItem.getGoodsId());
            Store store = storeMapper.selectById(goods.getStoreId());
            OrderInfoVo orderInfoVo = new OrderInfoVo();
            orderInfoVo.setOrderId(payInfo.getOrderId());
            orderInfoVo.setGoodsId(goods.getId());
            orderInfoVo.setStoreName(store.getHomeName());
            orderInfoVo.setGoodsImage(goods.getImage());
            orderInfoVo.setGoodsName(goods.getName());
            orderInfoVo.setSale(goods.getSale());
            orderInfoVo.setPrice(goods.getPrice());
            orderInfoVo.setNumber(orderItem.getNumber());
            orderInfoVo.setTotalPrice(goods.getPrice() *  orderItem.getNumber());
            list.add(orderInfoVo);
        });
        return list;
    }
}
